package cn.zhaoyuening.algorithms.dijkstra;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

class Vertex{
    private String name;
    private Map<Vertex, Integer> adjMap = new HashMap<>();

    public Vertex(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Vertex setName(String name) {
        this.name = name;
        return this;
    }

    public Integer getValByVertex(Vertex vertex) {
        return adjMap.get(vertex);
    }

    public Vertex addAdj(Vertex v, Integer val) {
        adjMap.put(v, val);
        return this;
    }

    public Set<Vertex> getAdjSet() {
        return adjMap.keySet();
    }

    @Override
    public String toString() {
        return this.name;
    }
}

public class Dijkstra {

    private Map<Vertex, Integer> valMap;
    private Set<Vertex> handledVertex;

    public Integer miniVal(Vertex startVertex, Vertex endVertex) {
        valMap = new HashMap<Vertex, Integer>();
        valMap.put(startVertex, 0);
        handledVertex = new HashSet<>();
        Vertex tmpVertex = startVertex;
        Set<Vertex> adjSet = null;
        while (tmpVertex != null) {
            handledVertex.add(tmpVertex);
            adjSet = tmpVertex.getAdjSet();
            for (Vertex v :
                    adjSet) {
                updateValMap(v, valMap.get(tmpVertex)+tmpVertex.getValByVertex(v));
//                找下个最小距离点
            }
            tmpVertex = findMiniValVertex();
        }
        return valMap.get(endVertex);
    }

    public Vertex findMiniValVertex() {
        Vertex miniVertex = null;
        Integer miniVal = Integer.MAX_VALUE;
        int tmpVal = 0;
        for (Vertex v :
                valMap.keySet()) {
            if (handledVertex.contains(v)) {
                continue;
            }
            tmpVal = valMap.get(v);
            if (miniVal > tmpVal) {
                miniVal = tmpVal;
                miniVertex = v;
            }
        }
        return miniVertex;
    }

    public boolean updateValMap(Vertex vertex,Integer val) {
        if (!valMap.containsKey(vertex)||val < valMap.get(vertex)) {
            valMap.put(vertex, val);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        Vertex s = new Vertex("S");
        Vertex a = new Vertex("A");
        Vertex b = new Vertex("B");
        Vertex e = new Vertex("E");

        s.addAdj(a, 6);
        s.addAdj(b, 2);
        b.addAdj(a, 3);
        a.addAdj(e, 1);

        Dijkstra dijkstra = new Dijkstra();
        Integer val = dijkstra.miniVal(s, e);
        System.out.println(val);

    }
}
